package com.lh0811.forge.pserv.basic.server.api.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lh0811.forge.dependency.basic_web.exception.CommonException;
import com.lh0811.forge.dependency.basic_web.response.ServerResponse;
import com.lh0811.forge.pserv.basic.api.api.BizNoBaseApi;
import com.lh0811.forge.pserv.basic.server.repository.dao.CommBizNoDao;
import com.lh0811.forge.pserv.basic.server.repository.entity.CommBizNo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.text.NumberFormat;

@Service
public class BizNoBaseApiImpl implements BizNoBaseApi {

    @Resource
    private CommBizNoDao commBizNoDao;


    /**
     * 获取下一个业务序号
     * 为了避免并发获取到重复的序号，必须要求在数据库事务级别串行处理该事务。
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
    public synchronized String getNextNumByBizType(String bizType) throws Exception {
        // 按照bizType获取序号信息
        QueryWrapper<CommBizNo> serialNumberQueryWrapper = new QueryWrapper<>();
        serialNumberQueryWrapper.lambda()
                .eq(CommBizNo::getBizType, bizType);
        CommBizNo serialNumber = commBizNoDao.getOne(serialNumberQueryWrapper);
        if (serialNumber == null) {
            throw CommonException.create(ServerResponse.createByError("未获取到序号配置"));
        }

        // 拼接序号
        StringBuffer sb = new StringBuffer(serialNumber.getPrefix());

        // 当前要获取到的序号
        Integer currentNum = serialNumber.getCurrentNum() + 1;

        // 获取到当前批次号
        StringBuffer endNumSb = new StringBuffer();
        if (serialNumber.getNumLen() == null && serialNumber.getNumLen().compareTo(0) == 0) {
            throw CommonException.create(ServerResponse.createByError(serialNumber.getPrefix() + " :未配置序号长度"));
        }
        for (int i = 1; i <= serialNumber.getNumLen(); i++) {
            endNumSb.append("9");
        }

        Integer batch = serialNumber.getBatch();
        if (currentNum > Integer.valueOf(endNumSb.toString())) {
            // 当前序号归1
            currentNum = 1;
            // 批次号+1
            batch += 1;
            if (String.valueOf(batch).length() > serialNumber.getBatchLen()) {
                throw CommonException.create(ServerResponse.createByError("当前批次号已经达到最大值,请扩充批次号长度或者重新创建序号记录"));
            }
        }

        // 组装序号
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置是否使用分组
        numberFormat.setGroupingUsed(false);
        // 设置最大整数位数
        numberFormat.setMaximumIntegerDigits(serialNumber.getBatchLen());
        // 设置最小整数位数
        numberFormat.setMinimumIntegerDigits(serialNumber.getBatchLen());

        // 拼接批次号
        sb.append(numberFormat.format(batch));

        // 设置最大整数位数
        numberFormat.setMaximumIntegerDigits(serialNumber.getNumLen());
        // 设置最小整数位数
        numberFormat.setMinimumIntegerDigits(serialNumber.getNumLen());

        // 拼接序号
        sb.append(numberFormat.format(currentNum));

        // 更新序号表数据
        serialNumber.setCurrentNum(currentNum);
        serialNumber.setBatch(batch);
        commBizNoDao.updateById(serialNumber);

        // 返回序号
        return sb.toString();
    }

}
